<template>
  <div class="relative top-0 left-0 customForm">
    <!-- form表单组件 -->
    <div>
      <slot name="header" />
    </div>
    <el-form
      ref="formEl"
      :size="props.size"
      :status-icon="false"
      :label-suffix="props.labelSuffix"
      :label-width="props.labelWidth"
      :label-position="props.labelPosition"
      :model="formData"
      :disabled="props.disabled"
    >
      <div class="flex flex-wrap gap-4">
        <div
          v-for="(item, index) in props.formItems"
          :key="item.field"
          :class="[item.visible ? '!hidden' : '', props.layoutVertical ? 'max-md:!w-full' : '']"
          :style="setLayoutSpan(item.span)"
        >
          <!-- 自定义 el-form-item 插槽-->
          <div v-if="item.type === 'itemSlot'">
            <div>
              <slot :name="item.slotName" v-bind="{ ...item, ...props.itemStyle }" />
            </div>
          </div>
          <div v-else class="h-full">
            <el-form-item
              v-if="!item.visible"
              :prop="item.field"
              for="null"
              :required="item.required"
              :label="item.label"
              :rules="!item.visible ? item.rules : undefined"
              :style="props.itemStyle"
              :class="[props.labelPosition !== 'left' ? 'Vertical' : '', defaultTo(item.className, '')]"
            >
              <template v-if="item.infoVisible" #label>
                <div class="flex items-center" :style="`width: ${item.required ? 'calc(100% - 10px)' : '100%'}`">
                  <div class="!font-[var($base-font-bold)] w-auto mr-[10px] text-nowrap" :style="`max-width: ${props.labelWidth}`">
                    {{ item.label }}
                  </div>
                  <div class="flex-1 overflow-hidden">
                    <slot :name="`${item.field}-label`" v-bind="item">
                      <el-tooltip class="box-item" effect="dark" :content="item.info" placement="top-start">
                        <el-alert type="error" :closable="false" :description="item.info" class="!p-[4px] !w-[fit-content] max-w-full">
                          <div class="truncate font-extralight px-1">
                            {{ item.info }}
                          </div>
                        </el-alert>
                      </el-tooltip>
                    </slot>
                  </div>
                </div>
              </template>
              <!-- input文本框 -->
              <template v-if="['input', 'password', 'textarea'].includes(item.type)">
                <el-input
                  :ref="'formItem' + index"
                  :type="item.type"
                  clearable
                  :placeholder="useI18n.global.t('customForm.index.434315-0') + item.label"
                  v-bind="{ ...item.otherOptions }"
                  :show-password="item.type === 'password'"
                  v-model="formData[`${item.field}`]"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  :formatter="(value) => `${value}`.replaceAll(' ', '')"
                  :parser="(value) => value.replaceAll(' ', '')"
                  @click="readonly = false"
                  @blur="removePlace(formData[`${item.field}`], item.field)"
                >
                  <template v-if="item.otherOptions?.leftUnit" #prefix>
                    <span>{{ item.otherOptions?.leftUnit }}</span>
                  </template>
                  <template v-if="item.otherOptions?.rightUnit" #suffix>
                    <span>{{ item.otherOptions?.rightUnit }}</span>
                  </template>
                  <template v-if="item.prepend" #prepend>
                    <div>
                      <el-select v-if="item.prepend.type === 'select'" v-model="formData[`${item.prepend.field}`]" v-bind="{ ...item.prepend.otherOptions }">
                        <el-option
                          v-for="(prependItem, prependIndex) in item.prepend.options"
                          :key="prependIndex"
                          :label="prependItem[item.prepend.optionsKey || 'label']"
                          :value="prependItem[item.prepend.optionsValue || 'value']"
                        />
                      </el-select>
                      <slot v-if="item.prepend.type === 'slot'" :name="`${item.field}-prepend`" v-bind="item.prepend" />
                    </div>
                  </template>
                  <template v-if="item.append" #append>
                    <div>
                      <el-select v-if="item.append.type === 'select'" v-model="formData[`${item.append.field}`]" v-bind="{ ...item.append.otherOptions }">
                        <el-option
                          v-for="(appendItem, appendIndex) in item.append.options"
                          :key="appendIndex"
                          :label="appendItem[item.append.optionsKey || 'label']"
                          :value="appendItem[item.append.optionsValue || 'value']"
                        />
                      </el-select>
                      <slot v-if="item.append.type === 'slot'" :name="`${item.field}-append`" v-bind="item.append" />
                    </div>
                  </template>
                </el-input>
              </template>
              <!-- cascader联级选择器 -->
              <template v-if="item.type === 'cascade'">
                <div class="w-full">
                  <el-cascader
                    :placeholder="useI18n.global.t('customForm.index.434315-1') + item.label"
                    v-model="formData[`${item.field}`]"
                    :options="item.options"
                    :style="props.layoutVertical ? 'width: 100% !important' : ''"
                    :props="{
                      label: item.optionsKey,
                      value: item.optionsValue,
                      children: item.optionsChildren,
                      checkStrictly: true,
                      emitPath: false
                    }"
                    valueKey="menuId"
                    clearable
                    @change="(val) => { formData[`${item.field}`] = defaultTo(formData[`${item.field}`], item.defaultValue) }"
                    v-bind="{ ...item.otherOptions }"
                  />
                </div>
              </template>
              <!-- select选择器 -->
              <template v-if="item.type === 'select'">
                <div class="w-full h-full">
                  <el-select
                    clearable
                    filterable
                    :placeholder="useI18n.global.t('customForm.index.434315-1') + item.label"
                    :style="props.layoutVertical ? 'width: 100% !important' : ''"
                    v-bind="{ ...item.otherOptions }"
                    v-model="formData[`${item.field}`]"
                  >
                    <template>
                      <el-option
                        v-for="option in item.options"
                        :key="option[item.optionsValue || 'value']"
                        :label="option[item.optionsKey || 'label']"
                        :value="option[item.optionsValue || 'value']"
                      >
                      </el-option>
                    </template>
                  </el-select>
                </div>
              </template>
              <!-- tree-select选择器 -->
              <template v-if="item.type === 'treeSelect'">
                <div class="w-full h-full">
                  <el-tree-select
                    v-model="formData[`${item.field}`]"
                    check-strictly
                    lazy
                    :data="defaultTo(item.options, [])"
                    v-bind="{ ...item.otherOptions }"
                    :render-after-expand="false"
                    show-checkbox
                  />
                </div>
              </template>
              <!-- 日期选择器 -->
              <template v-if="item.type === 'datePicker'">
                <el-date-picker
                  v-model="formData[`${item.field}`]"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  :format="item.format || 'YYYY-MM-DD'"
                  :value-format="item.valueFormat || 'YYYY-MM-DD'"
                  v-bind="{ ...item.otherOptions }"
                  clearable
                />
              </template>
              <!-- 日期间隔选择器 -->
              <template v-if="item.type === 'daterange'">
                <el-date-picker
                  v-model="formData[`${item.field}`]"
                  type="daterange"
                  range-separator="-"
                  :start-placeholder="useI18n.global.t('customForm.index.434315-2')"
                  :end-placeholder="useI18n.global.t('customForm.index.434315-3')"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  v-bind="{
                    ...item.otherOptions
                  }"
                  @change="pickerChange($event, item.beginField, item.endField, item.valueFormat)"
                  clearable
                />
              </template>
              <!-- inputNumber计数器 -->
              <template v-if="item.type === 'inputNumber'">
                <el-input-number
                  v-bind="{ ...item.otherOptions }"
                  v-model="formData[`${item.field}`]"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  clearable
                />
              </template>
              <!-- 自定义数字输入框 -->
              <template v-if="item.type === 'customNumber'">
                <custom-input-number
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  :model-value="formData[`${item.field}`]"
                  v-bind="{ ...item.otherOptions }"
                  @update="
                    row => {
                      formData[`${item.field}`] = row
                    }
                  "
                >
                  <template #customAppend>
                    <slot name="customNumberAppend" />
                  </template>
                </custom-input-number>
              </template>
              <!-- 单选多选按钮 -->
              <template v-if="item.type === 'radio'">
                <el-radio-group
                  v-model="formData[`${item.field}`]"
                  :disabled="item.otherOptions?.disabled || false"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                >
                  <template>
                    <el-radio
                      v-for="option in item.options"
                      :label="option[item.optionsKey || 'label']"
                      :value="option[item.optionsValue || 'value']"
                      :key="option.label"
                    >
                      {{ option[item.optionsKey || 'label'] }}{{ item?.addintial }}
                    </el-radio>
                  </template>
                </el-radio-group>
              </template>
              <!-- 上传图片 -->
              <template v-if="item.type === 'upload'">
                <file-upload
                  :limit="item.limit || 1"
                  :fileType="item.fileType || ['png', 'jpg', 'jpeg', 'pdf']"
                  :is-show-tip="item.isShowTip || false"
                  :model-value="formData[`${item.field}`]"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  v-bind="{
                    ...item.otherOptions
                  }"
                  @update:modelValue="handUploadFIle($event, item.limit, item.field)"
                />
              </template>
              <!-- 上传文件 -->
              <template v-if="item.type === 'customUpload'">
                <custom-upload
                  :limit="item.limit || 1"
                  :field="item.field"
                  :fileType="item.fileType || ['png', 'jpg', 'jpeg', 'pdf']"
                  :is-show-tip="item.isShowTip || false"
                  :model-value="formData[`${item.field}`]"
                  :style="props.layoutVertical ? 'width: 100% !important' : ''"
                  @update:modelValue="handUploadFIle($event, item.limit, item.field)"
                  v-bind="{ ...item.otherOptions }"
                />
              </template>
<!--              &lt;!&ndash; 富文本编辑器 &ndash;&gt;-->
<!--              <template v-if="item.type === 'editor'">-->
<!--                <editor-->
<!--                  v-model="formData[`${item.field}`]"-->
<!--                  v-bind="{-->
<!--                    ...item.otherOptions-->
<!--                  }"-->
<!--                />-->
<!--              </template>-->
              <!-- 表单项插槽 -->
              <template v-if="item.type === 'slot'">
                <slot :name="item.slotName" v-bind="item"> </slot>
              </template>
            </el-form-item>
          </div>
        </div>
        <div v-if="props.rightTemplateVisible" :style="props.rightStyle" :class="props.layoutVertical ? '!w-full' : ''">
          <slot name="right" />
        </div>
      </div>
    </el-form>
    <div class="footer">
      <slot name="footer" class="mt-3" />
    </div>
  </div>
</template>

<script setup>
import customInputNumber from '@/components/customInputNumber'
import customUpload from '@/components/customUpload'
import { propsConfig } from './props.js'
import dayjs from 'dayjs'
import FileUpload from '@/components/FileUpload/index.vue'
import { defaultTo } from '@/utils/setting.js'
import useI18n from "@/i18n/index.js";

const instance = getCurrentInstance()
const props = defineProps(propsConfig)
const emits = defineEmits(['update'])

// const formData = ref({ ...props.modelValue })
const formEl = ref() // 表单对象
const formData = computed({
  get: () => {
    return props.modelValue
  },
  set: newValue => {
    emits('update', newValue)
  }
})

const readonly = ref(true) // 阻止规避浏览器的自动填充密码功能

// watch(
//   () => props.modelValue,
//   newValue => {
//     formData.value = newValue
//   },
//   {
//     deep: true,
//     immediate: true
//   }
// )
//
// watch(
//   () => formData.value,
//   newValue => {
//     emits('update', newValue)
//   },
//   {
//     deep: true
//   }
// )

const clear = () => {
  formData.value = {}
  clearValidate()
}

const clearValidate = () => {
  formEl.value.clearValidate()
}

// 触发校验
const haveValidate = () => {
  return new Promise((resolve, reject) => {
    formEl.value.validate((valid, fields) => {
      resolve(valid)
    })
  })
}

// 时间区间选择器变化
const pickerChange = (value, beginField, endField, format) => {
  if (value) {
    formData.value[beginField] = dayjs(value[0]).format(format)
    formData.value[endField] = dayjs(value[1]).format(format)
  } else {
    delete formData.value[beginField]
    delete formData.value[endField]
  }
}

// 文件列表更新方法回调数据
const handUploadFIle = (list, limit = 1, field) => {
  // formData.value[showField] = list // 展示列表赋值
  // formData.value[field] =
  //   limit <= 1
  //     ? list[0]?.id
  //     : list.map(item => {
  //         return item.id
  //       }) // 提交字段

  // if (limit <= 1) {
  //   formData.value[customField] = list[0]?.id
  //   formData.value[field] = list[0]?.url
  // } else {
  //   formData.value[field] = list.map(item => {
  //     return {
  //       ...item,
  //       [field]: item?.url,
  //       [customField]: item.id || formData.value[customField]
  //     }
  //   })
  //   delete formData.value[customField]
  // }

  formData.value[field] = list
}

// 去除空格
const removePlace = (value, field) => {
  if (value) formData.value[field] = value.replaceAll(" ","")
}

// 提交表单
const submitForm = () => {
  new Promise(async (resolve, reject) => {
    const flag = await haveValidate()
    if (flag) {
      resolve()
    } else {
      resolve()
    }
  })
}

// 设置布局 更具传入的配置布局 默认间隔1rem
const setLayoutSpan = span => {
  if (props.layoutVertical) {
    if (span) {
      const gutter = 24 / span - 1 // 间隔宽度rem (24 / span - 1) * 1
      const rate = span / 24
      const width = `calc((100% - ${gutter}rem) * ${rate})`
      return {
        width: width
      }
    } else {
      return {
        width: '100%'
      }
    }
  } else {
    return {}
  }
}

defineExpose({ haveValidate })
</script>

<style scoped lang="scss">
.customForm {
  :deep(.el-form-item__label) {
    width: 100%;
    min-height: 32px;
    color: unset;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    padding: 0;
    padding-right: 10px;
    position: relative;

    //&::before {
    //  position: absolute;
    //  top: -5px;
    //  left: -8px;
    //}
  }

  .Vertical {
    :deep(.el-form-item__label) {
      padding-right: 0 !important;
    }
  }

  .el-row {
    .el-col {
      .gutter {
        border: 1px solid #ccc;
      }
    }
  }

  //:deep(.el-range-editor--default) {
  //  height: 38px;
  //}
}
</style>
